Uurige, kuidas Python muudab finantsriskide juhtimist. Õppige looma tugevaid süsteeme turu-, krediidi- ja operatsiooniriski jaoks, kasutades võimsaid teeke.
Python finantsriskide juhtimises: Tugevate süsteemide ehitamine globaalsel turul
Tänapäeva omavahel seotud globaalses majanduses on finantsturud keerukamad ja volatiilsemad kui kunagi varem. Institutsioonidele, alates rahvusvahelistest pankadest Londonis ja New Yorgis kuni arenevate finantstehnoloogia idufirmadeni Singapuris ja São Paulos, on võime riske täpselt tuvastada, mõõta ja maandada mitte ainult regulatiivne nõue, vaid ka ellujäämise ja edu alustala. Traditsioonilised riskijuhtimise vahendid, mis tuginevad sageli patenteeritud, paindumatule ja kulukale tarkvarale, ei suuda üha enam ajaga kaasas käia. Siin astubki lavale Python, mitte ainult programmeerimiskeelena, vaid revolutsioonilise jõuna, mis demokratiseerib kvantitatiivset rahandust ja annab uue põlvkonna riskispetsialistidele võimekuse.
See põhjalik juhend uurib, miks on Pythonist saanud vaieldamatult eelistatuim keel kaasaegsete, skaleeritavate ja keerukate riskijuhtimissüsteemide ehitamiseks. Süveneme selle võimsasse ökosüsteemi, loome riskimootori põhikomponentide arhitektuuri ja pakume praktilisi, koodipõhiseid näiteid turu-, krediidi- ja operatsiooniriskide modelleerimiseks. Olenemata sellest, kas olete kogenud kvantitatiivne analüütik, riskijuht, kes soovib oma tööriistakomplekti uuendada, või arendaja, kes siseneb finantsvaldkonda, pakub see artikkel teile teekaardi Pythoni kasutamiseks maailmatasemel riskijuhtimises.
Pythoni ületamatud eelised riskispetsialistidele
Pythoni esiletõus finantsmaailmas ei ole juhus. See tuleneb ainulaadsest kombinatsioonist võimsusest, lihtsusest ja võrratust ökosüsteemist, mis muudab selle ideaalselt sobivaks andmemahukate ja arvutuslikult nõudlike riskimodelleerimise ülesannete jaoks. Kuigi ka teistel keeltel on oma koht, pakub Python terviklikku paketti, mida on raske ületada.
Rikkalik ja küps ökosüsteem kvantitatiivseks rahanduseks
Pythoni tõeline jõud peitub selle laiaulatuslikus avatud lähtekoodiga teekide kogumis, mis pakuvad eelnevalt ehitatud ja kõrgelt optimeeritud tööriistu peaaegu igaks finantsanalüüsi ülesandeks. See teadusarvutuste pakett on Pythonis riskimodelleerimise alustala:
- NumPy (Numerical Python): Fundamentaalne pakett numbrilisteks arvutusteks. See pakub võimsaid N-mõõtmelisi massiivi objekte, keerukaid ringhäälingu funktsioone (broadcasting) ning tööriistu C/C++ ja Fortrani koodi integreerimiseks. Riskijuhtimises on see mootoriks igale arvutusele, mis hõlmab suuri arvumaatrikseid, alates portfelli tootlustest kuni simulatsiooni väljunditeni.
- Pandas: NumPy peale ehitatud Pandas pakub suure jõudlusega ja lihtsalt kasutatavaid andmestruktuure – peamiselt DataFrame'i – ning andmeanalüüsi tööriistu. See on kvintessentsiaalne tööriist aegridade ja struktureeritud finantsandmete sisselugemiseks, puhastamiseks, teisendamiseks, manipuleerimiseks ja analüüsimiseks.
- SciPy (Scientific Python): See teek sisaldab mooduleid optimeerimiseks, lineaaralgebraks, integreerimiseks, interpoleerimiseks ja statistikaks. Riskijuhtide jaoks on SciPy statistikmoodul (`scipy.stats`) hindamatu väärtusega tõenäosusjaotuste sobitamiseks kahjuandmetele, mis on oluline samm operatsiooniriski modelleerimisel ja Monte Carlo simulatsioonide läbiviimisel.
- Matplotlib & Plotly: Tõhus riskijuhtimine on sama palju seotud kommunikatsiooniga kui arvutamisega. Matplotlib on standard staatiliste, publikatsioonikvaliteediga graafikute ja diagrammide loomiseks. Plotly koos oma veebirakenduste raamistiku Dashiga võimaldab luua interaktiivseid, dünaamilisi armatuurlaudu, mis lubavad sidusrühmadel riskipositsioone reaalajas uurida.
- Scikit-learn: Esmaklassiline teek masinõppeks Pythonis. Krediidiriski jaoks pakub see lihtsat juurdepääsu algoritmidele nagu logistiline regressioon, gradientvõimendus (Gradient Boosting) ja juhuslikud metsad (Random Forests) ennustavate krediidiskoori mudelite loomiseks. Samuti pakub see tugevat raamistikku mudelite treenimiseks, testimiseks ja valideerimiseks.
Arenduskiirus ja loetavus
Pythoni süntaks on tuntud oma puhtuse ja intuitiivsuse poolest, mida sageli kirjeldatakse kui peaaegu täidetavat pseudokoodi. See loetavus vähendab oluliselt aega ja vaeva, mis kulub keeruka finantsmudeli tõlkimiseks uurimistööst või teoreetilisest kontseptsioonist töötavaks koodiks. See võimaldab kiiret prototüüpimist, lubades riskimeeskondadel testida uusi ideid ja strateegiaid palju kiiremini kui madalama taseme keeltega nagu C++. Tulemuseks on agiilsem ja reageerimisvõimelisem riskijuhtimisfunktsioon.
Avatud lähtekood ja kulutõhusus
Patenteeritud tarkvaralitsentsid platvormidele nagu MATLAB või SAS võivad institutsioonidele maksta tuhandeid dollareid kasutaja kohta aastas. Python ja kogu selle teaduslik ökosüsteem on täiesti tasuta ja avatud lähtekoodiga. See alandab dramaatiliselt sisenemisbarjääri, võimaldades väiksematel ettevõtetel, riskifondidel ja isegi üksikprofessionaalidel pääseda ligi samadele võimsatele tööriistadele nagu suurimad globaalsed pangad. See soodustab innovatsiooni ja võrdsustab tingimusi rahvusvahelisel finantsmaastikul.
Globaalne koostöökogukond
Pythoni taga on üks maailma suurimaid ja aktiivsemaid arendajakogukondi. Iga finantsmodelleerimise probleemi puhul on väga tõenäoline, et keegi on sellega juba silmitsi seisnud, selle lahendanud ja lahendust jaganud. See koostöövaim väljendub ulatuslikus dokumentatsioonis, avalikes foorumites nagu Stack Overflow ning pidevas uute teekide ja tööriistade voos. See globaalne võrgustik pakub arendajatele ja analüütikutele uskumatut tugisüsteemi, olenemata nende geograafilisest asukohast.
Kaasaegse riskijuhtimissüsteemi arhitektuuri loomine Pythonis
Tugeva riskijuhtimissüsteemi ehitamine ei tähenda ühe skripti kirjutamist. See tähendab modulaarse, skaleeritava arhitektuuri kavandamist, kus erinevad komponendid töötavad sujuvalt koos. Tüüpilise Pythonil põhineva süsteemi saab jagada viieks peamiseks kihiks.
1. Andmete sisselugemine ja ETL (Extract, Transform, Load)
Iga riskimudeli aluseks on kvaliteetsed andmed. See kiht vastutab turuandmete (nt aktsiahinnad, intressimäärad, valuutakursid API-dest nagu Bloomberg või Refinitiv), sisemiste positsiooniandmete andmebaasidest ja muude asjakohaste andmekogumite hankimise eest. Python koos teekidega nagu Pandas, SQLAlchemy (andmebaasidega suhtlemiseks) ja Requests (veebi API-de jaoks) on selles suurepärane. 'ETL' protsess hõlmab andmete puhastamist (puuduvate väärtuste käsitlemine, vigade parandamine) ja nende teisendamist struktureeritud vormingusse, tavaliselt Pandas DataFrame'i, mis on analüüsiks valmis.
2. Modelleerimise põhimootor
See on riskisüsteemi süda, kus tegelikud riskiarvutused tehakse. See mootor sisaldab Pythoni mooduleid erinevate riskitüüpide jaoks. Näiteks võib tururiski moodul sisaldada funktsioone väärtusriski (VaR) arvutamiseks, samas kui krediidiriski moodul võib sisaldada masinõppe mudelit maksejõuetuse ennustamiseks. Siin teevad raske töö teegid nagu NumPy, SciPy ja Scikit-learn.
3. Stsenaariumide genereerimine ja stressitestimine
See komponent on loodud vastama olulistele 'mis-siis-kui' küsimustele. Mis juhtub meie portfelliga, kui intressimäärad tõusevad 2%? Milline on 2008. aasta kriisiga sarnase äkilise aktsiaturu krahhi mõju? See kiht kasutab Pythonit, et programmiliselt määratleda ja rakendada hüpoteetilisi või ajaloolisi šokke sisendandmetele ning seejärel suunab stressitud andmed läbi modelleerimise põhimootori, et kvantifitseerida potentsiaalseid kahjumeid.
4. Aruandlus, visualiseerimine ja teavitamine
Toored riskinumbrid on vähe kasulikud, kui neid ei saa selgelt edastada otsustajatele, kauplejatele ja regulaatoritele. See kiht vastutab modelleerimismootori väljundite kokkuvõtmise eest seeditavatesse vormingutesse. See võib ulatuda lihtsatest PDF-aruannetest, mis on loodud teekidega nagu ReportLab, kuni keerukate, interaktiivsete veebipõhiste armatuurlaudadeni, mis on ehitatud Plotly Dash või Streamlit abil. See võib sisaldada ka teavitussüsteemi, mis teavitab riskijuhte automaatselt, kui teatud lävepakud on ületatud.
5. Mudeli valideerimine ja tagasitestimine (Backtesting)
Riskimudel on ainult nii hea, kui on selle ennustustäpsus. Tagasitestimise kiht on mudelite toimivuse valideerimiseks ülioluline. VaR-mudeli puhul hõlmab see antud päeval ennustatud VaR-i võrdlemist tegeliku kasumi või kahjumiga, mis toimus järgmisel päeval. Käivitades seda võrdlust pika ajaloolise perioodi jooksul, saame hinnata, kas mudel toimib ootuspäraselt. Pythoni andmete manipuleerimise ja statistilised tööriistad muudavad paindliku tagasitestimise raamistiku loomise lihtsaks ülesandeks.
Praktilised rakendused: Peamiste riskide modelleerimine Pythoniga
Liigume teooriast praktikasse. Siin on lihtsustatud, illustreerivad näited, kuidas modelleerida kolme peamist finantsriski kategooriat, kasutades Pythoni põhiteeke.
Tururisk: Volatiilsuse taltsutamine
Tururisk on kahjumi risk, mis tuleneb turuhindade, näiteks aktsiahindade, intressimäärade ja valuutakursside liikumisest.
Väärtusriski (VaR) arvutamine
Väärtusrisk (Value at Risk ehk VaR) on statistiline mõõdik, mis kvantifitseerib finantsriski taset ettevõttes või portfellis teatud ajaperioodi jooksul. 99% 1-päevane VaR 1 miljon dollarit tähendab, et on 1% tõenäosus, et portfell kaotab järgmise päeva jooksul rohkem kui 1 miljon dollarit.
Ajalooline VaR näide: See on kõige lihtsam meetod. See eeldab, et mineviku tootlus on hea tuleviku riski indikaator. Me lihtsalt vaatame oma portfelli ajaloolisi tootlusi ja leiame punkti, mis vastab meie soovitud usaldustasandile.
import numpy as np
import pandas as pd
# Assume we have a DataFrame 'portfolio_returns' with daily returns of our portfolio
# In a real system, this would be calculated from positions and historical market data
# Generate some sample data for demonstration
np.random.seed(42)
returns_data = np.random.normal(loc=0.0005, scale=0.015, size=1000)
portfolio_returns = pd.Series(returns_data, name="daily_return")
# Define VaR parameters
confidence_level = 0.99
# Calculate Historical VaR
# For a 99% confidence level, we want the 1st percentile of returns (since losses are negative)
VaR_99 = portfolio_returns.quantile(1 - confidence_level)
print(f"Portfelli päevatootlused (esimesed 5):")
print(portfolio_returns.head())
print("-------------------------------------")
print(f"99% päevane ajalooline VaR: {VaR_99:.4f}")
print(f"See tähendab, et oleme 99% kindlad, et meie päevane kahjum ei ületa {-VaR_99*100:.2f}%")
Teised levinud VaR-meetodid hõlmavad parameetrilist VaR-i (mis eeldab, et tootlused järgivad normaaljaotust) ja Monte Carlo VaR-i (mis simuleerib tuhandeid võimalikke tulevikutulemusi).
Enamat kui VaR: Oodatav puudujääk (Expected Shortfall, ES)
VaR-i peamine kriitika on see, et see ütleb teile maksimaalse võimaliku kaotuse, kuid mitte seda, kui palju rohkem te võiksite halvima stsenaariumi korral kaotada. Oodatav puudujääk (Expected Shortfall, ES), tuntud ka kui tingimuslik VaR (Conditional VaR, CVaR), vastab sellele küsimusele. See arvutab keskmise kahjumi nendel päevadel, kui kahjum ületab VaR-i läve.
# Calculate Expected Shortfall for the 99% confidence level
# This is the average of all returns that are worse than the VaR_99
is_breach = portfolio_returns <= VaR_99
ES_99 = portfolio_returns[is_breach].mean()
print(f"99% päevane oodatav puudujääk: {ES_99:.4f}")
print(f"See tähendab, et 1% halvimal päeval on oodatav keskmine kahjum {-ES_99*100:.2f}%")
Krediidirisk: Maksejõuetuse kvantifitseerimine
Krediidirisk on kahjumi risk, kui laenuvõtja või vastaspool ei suuda oma võlakohustusi täita. See on peamine mure pankadele, laenuandjatele ja igale krediidiriskiga kokku puutuvale institutsioonile.
Ennustava skoorimismudeli ehitamine
Masinõpet kasutatakse laialdaselt krediidiskoori mudelite loomiseks, mis ennustavad antud laenuvõtja maksejõuetuse tõenäosust (probability of default, PD) tema omaduste põhjal (nt sissetulek, vanus, olemasolev võlg, makseajalugu). Pythoni Scikit-learn teek muudab selle protsessi uskumatult kättesaadavaks.
Kontseptuaalne koodinäide Scikit-learniga:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix
# 1. Andmete laadimine ja ettevalmistamine (kontseptuaalne)
# Oletame, et 'loan_data.csv' sisaldab tunnuseid nagu 'income', 'age', 'loan_amount'
# ja sihtmuutujat 'default' (1, kui maksejõuetu, 0 muidu)
# data = pd.read_csv('loan_data.csv')
# X = data[['income', 'age', 'loan_amount']]
# y = data['default']
# Demonstratsiooniks loome sünteetilised andmed
data = {'income': [50, 20, 80, 120, 40, 30],
'loan_amount': [10, 5, 20, 40, 15, 12],
'default': [0, 1, 0, 0, 1, 0]}
df = pd.DataFrame(data)
X = df[['income', 'loan_amount']]
y = df['default']
# 2. Andmete jagamine treening- ja testimiskogumiteks
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 3. Mudeli lähtestamine ja treenimine
# Logistiline regressioon on levinud valik binaarseks klassifitseerimiseks (maksejõuetu/maksejõuline)
model = LogisticRegression()
model.fit(X_train, y_train)
# 4. Ennustuste tegemine uute andmete põhjal
y_pred = model.predict(X_test)
# 5. Mudeli jõudluse hindamine
accuracy = accuracy_score(y_test, y_pred)
print(f"Mudeli täpsus: {accuracy:.2f}")
# 6. Uue taotleja maksejõuetuse tõenäosuse ennustamine
new_applicant = pd.DataFrame([{'income': 60, 'loan_amount': 25}])
probability_of_default = model.predict_proba(new_applicant)[:, 1]
print(f"Ennustatud maksejõuetuse tõenäosus uuele taotlejale: {probability_of_default[0]:.4f}")
Operatsioonirisk: Ootamatu modelleerimine
Operatsioonirisk on kahjumi risk, mis tuleneb ebaõnnestunud sisemistest protsessidest, inimestest, süsteemidest või välistest sündmustest. See hõlmab kõike alates töötajate pettustest ja IT-süsteemide tõrgetest kuni loodusõnnetuste ja küberrünnakuteni. Seda on kurikuulsalt raske modelleerida kahjusündmuste harvaesineva, kuid suure mõjuga olemuse tõttu (nn 'paksusabalised' jaotused).
Kahjude jaotuse lähenemisviis (Loss Distribution Approach, LDA)
Standardne tehnika on kahjude jaotuse lähenemisviis (LDA). See hõlmab kahe asja eraldi modelleerimist: kahjusündmuste sagedus (kui tihti need toimuvad) ja iga kahju tõsidus (kui suur on rahaline mõju). Seejärel saame kasutada Monte Carlo simulatsiooni, et kombineerida need kaks jaotust ja luua potentsiaalsete operatsioonikahjude üldine jaotus aasta kohta.
Kontseptuaalne koodinäide SciPy'ga:
import numpy as np
from scipy import stats
# Simulatsiooni parameetrid
n_simulations = 100000 # Simuleeritud aastate arv
# 1. Kahjude sageduse modelleerimine
# Oletame, et ajaloolised andmed näitavad, et meil on keskmiselt 5 kahjusündmust aastas.
# Poissoni jaotus sobib hästi sündmuste arvu modelleerimiseks intervallis.
avg_events_per_year = 5
loss_frequency = stats.poisson(mu=avg_events_per_year)
# Simuleerime sündmuste arvu igaks aastaks
simulated_event_counts = loss_frequency.rvs(n_simulations)
# 2. Kahjude tõsiduse modelleerimine
# Oletame, et ajaloolised kahjud, kui need toimuvad, järgivad logaritmilist normaaljaotust.
# See on tavaline, kuna kahjud ei saa olla negatiivsed ja neil võib olla suuri erisusi.
# (Parameetrid on tuletatud ajaloolistest andmetest)
mu = 10
sigma = 1.5
loss_severity = stats.lognorm(s=sigma, scale=np.exp(mu))
# 3. Monte Carlo simulatsiooni käivitamine
total_annual_losses = []
for count in simulated_event_counts:
if count > 0:
# Iga simuleeritud aasta jaoks võtame 'count' arvu kahjusid tõsiduse jaotusest
losses = loss_severity.rvs(count)
total_annual_losses.append(np.sum(losses))
else:
total_annual_losses.append(0)
# 4. Tulemuste analüüsimine
# Meil on nüüd võimalike aastaste operatsioonikahjude jaotus
total_annual_losses = np.array(total_annual_losses)
# Arvutame operatsiooniriski VaR-i (nt 99.9% usaldustasandil regulatiivse kapitali jaoks)
op_risk_VaR_999 = np.percentile(total_annual_losses, 99.9)
print(f"Simuleeritud keskmine aastane kahjum: ${np.mean(total_annual_losses):,.2f}")
print(f"99.9% operatsiooniriski VaR: ${op_risk_VaR_999:,.2f}")
Mudelist masinani: Parimad praktikad tootmiskõlbulike süsteemide jaoks
Mudeli viimine Jupyter Notebookist usaldusväärsesse, tootmisvalmis süsteemi nõuab distsipliini ja inseneriteaduse parimaid praktikaid.
Koodi kvaliteet ja hooldatavus
Süsteemide puhul, millele finantsasutused tuginevad, on puhas, hästi dokumenteeritud ja testitav kood vältimatu. Objektorienteeritud programmeerimise (OOP) lähenemisviisi kasutuselevõtt, kus iga riskimudel on 'klass' oma meetodite ja atribuutidega, parandab oluliselt organiseeritust. Giti kasutamine versioonihalduseks on muudatuste jälgimiseks ja meeskonnaga koostöö tegemiseks hädavajalik. Lõpuks tagab automatiseeritud testide kirjutamine raamistikega nagu pytest, et koodi muudatused ei riku olemasolevat funktsionaalsust, mis on mudeliriski juhtimise kriitiline aspekt.
Jõudlus suuremahuliselt
Kuigi Pythoni koodi on kiire kirjutada, võib puhas Pythoni kood olla raskete arvutuste jaoks aeglane. Jõudluse võti on kasutada teeke, mis on kapoti all kirjutatud C-s või Fortranis. Esimene reegel on kasutada vektoriseerimist NumPy ja Pandasega kõikjal, kus võimalik, vältides aeglaseid Pythoni tsükleid. Koodiosade jaoks, mis on endiselt pudelikaelad, võivad teegid nagu Numba arvutusi märkimisväärselt kiirendada lihtsa funktsioonidekoraatoriga. Tõeliselt massiivsete andmekogumite jaoks, mis ei mahu ühe masina mällu, võimaldavad raamistikud nagu Dask paralleelida Pandas ja NumPy arvutusi mitme tuuma või isegi masinaklastri vahel.
Turvaline ja skaleeritav kasutuselevõtt
Riskimudel on kõige kasulikum, kui selle tulemused on teistele süsteemidele või kasutajatele nõudmisel kättesaadavad. Levinud praktika on mähkida riskimootor veebi API-sse, kasutades kaasaegset raamistikku nagu FastAPI või Flask. See võimaldab teistel rakendustel taotleda riskiarvutust standardse HTTP-päringu kaudu. Et tagada süsteemi järjepidev toimimine erinevates keskkondades (arendaja sülearvuti, testimisserver, tootmisserver), kasutatakse Dockerit, et pakendada Pythoni rakendus ja kõik selle sõltuvused kaasaskantavasse konteinerisse.
Tulevik on nüüd: Tehisintellekt, pilv ja reaalajas risk
Riskijuhtimise valdkond areneb pidevalt ja Python on selle muutuse esirinnas olevate tehnoloogiate eesotsas.
Masinõpe täiustatud ülevaadete jaoks
Masinõppe (ML) ja tehisintellekti (AI) kasutamine laieneb kaugemale krediidiskoorimisest. Seda kasutatakse nüüd keerukaks pettuste avastamiseks, anomaalsete kauplemismustrite tuvastamiseks ja isegi loomuliku keele töötluse (NLP) kasutamiseks uudiste ja sotsiaalmeedia meelsuse analüüsimiseks, et ennustada turušokke.
Pilvandmetöötluse jõud
Pilveplatvormid nagu Amazon Web Services (AWS), Google Cloud Platform (GCP) ja Microsoft Azure pakuvad nõudmisel juurdepääsu tohutule arvutusvõimsusele. See võimaldab ettevõtetel käivitada massiivseid Monte Carlo simulatsioone või treenida keerukaid masinõppe mudeleid, ilma et peaksid investeerima ja hooldama kallist kohapealset riistvara.
Üleminek reaalajas jälgimisele
Traditsiooniliselt genereeriti paljud riskiraportid partiidena päeva lõpus. Kaasaegne eesmärk on liikuda reaalajas riskijälgimise suunas. See hõlmab Pythoni riskimootorite integreerimist voogedastustehnoloogiatega nagu Apache Kafka ja Spark Streaming, et pakkuda kauplejatele ja riskijuhtidele sekunditäpset ülevaadet nende riskipositsioonidest.
Kokkuvõte: Oma riskistrateegia võimestamine Pythoniga
Python on finantsriskide juhtimise maastikku põhjalikult ümber kujundanud. Selle kombinatsioon võimsast, spetsialiseerunud ökosüsteemist, kasutuslihtsusest ja nullkulust on murdnud barjäärid keerukale kvantitatiivsele analüüsile. See võimaldab luua läbipaistvaid, paindlikke ja skaleeritavaid riskisüsteeme, mida saab kohandada iga finantsasutuse unikaalsetele vajadustele, ükskõik kus maailmas.
Pythonit omaks võttes saavad organisatsioonid eemalduda jäikadest, musta kasti lahendustest ning edendada ettevõttesisese innovatsiooni ja omanikutunde kultuuri. See annab riskijuhtidele ja kvantitatiivsetele analüütikutele võimekuse mitte ainult oma mudeleid mõista, vaid neid ka ehitada, täiustada ja kohandada pidevalt muutuvale globaalsele turule. Teekond lihtsast VaR-skriptist täiemahulise, üle-ettevõttelise riskijuhtimissüsteemini on väljakutseid pakkuv, kuid Pythoni mitmekülgse tööriistakomplektiga pole see kunagi olnud saavutatavam.